#ifndef __BLOCK_HH__
#define __BLOCK_HH__

#include <opengl/texture.h>
#include <opengl/shader.h>
#include <opengl/vertex.h>
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <string>
#include <vector>

namespace mc
{
// 方块基类
class Block
{
public:
    // 构造函数
    Block(unsigned int textureCnt);
    virtual ~Block();

    // 放置方块
    void place(const glm::vec3& position, bool upadate = true);
    void place(float x, float y, float z, bool update = true)
    { this->place(glm::vec3(x, y, z), update); }

    // 移除方块
    void remove(const glm::vec3& position, bool update = true);
    void remove(float x, float y, float z, bool update = true)
    { this->remove(glm::vec3(x, y, z), update); }

    // 更新实例化数组
    virtual void updatePositions() = 0;

    // 渲染函数
    virtual void draw() = 0;

    // 纹理数组
    virtual opengl::Texture** textures() = 0;

public:
    // 准备渲染
    static void prepareRender(const glm::mat4& view);

    // 加载方块着色器程序
    static void createShader(const glm::mat4& projection);

protected:
    // 实例化数组缓冲对象
    opengl::VertexBuffer _instanceVBO;
    // 方块的位置数组
    std::vector<glm::mat4> _instanceMatrices;

public:
    // 所有方块公用着色器与顶点数据
    static opengl::Shader shader;
    static float vertices[];

    std::vector<glm::mat4>& positions()
    { return this->_instanceMatrices; }
};

// 1 种纹理的方块子类
class OneTextureBlock : public Block
{
public:
    OneTextureBlock();
    virtual ~OneTextureBlock();
    virtual void draw() override;
    virtual void updatePositions() override;

protected:
    opengl::VertexArray _vao;
    opengl::VertexBuffer _vbo;
};

// 2 种纹理的方块子类
class TwoTexturesBlock : public Block
{
public:
    TwoTexturesBlock();
    virtual ~TwoTexturesBlock();
    virtual void draw() override;
    virtual void updatePositions() override;

protected:
    opengl::VertexArray _vaos[2];
    opengl::VertexBuffer _vbos[2];
};

// 3 种纹理的方块子类
class ThreeTexturesBlock : public Block
{
public:
    ThreeTexturesBlock();
    virtual ~ThreeTexturesBlock();
    virtual void draw() override;
    virtual void updatePositions() override;

protected:
    opengl::VertexArray _vaos[3];
    opengl::VertexBuffer _vbos[3];
};

// 4 种纹理的方块子类
class FourTexturesBlock : public Block
{
public:
    FourTexturesBlock();
    virtual ~FourTexturesBlock();
    virtual void draw() override;
    virtual void updatePositions() override;

protected:
    opengl::VertexArray _vaos[4];
    opengl::VertexBuffer _vbos[4];
};

// 创建实体方块类宏定义
#define CREATE_BLOCK(className, baseClassName, textureCount) \
class className : public baseClassName\
{\
public:\
    className() : baseClassName() {}\
    virtual opengl::Texture** textures() override\
    {\
        return className::_textures;\
    }\
    static opengl::Texture* _textures[textureCount];\
};\

// 创建实体方块类宏定义
#define CREATE_OVERRIDE_DRAW_BLOCK(className, baseClassName, textureCount) \
class className : public baseClassName\
{\
public:\
    className() : baseClassName() {}\
    virtual void draw() override;\
    virtual opengl::Texture** textures() override\
    {\
        return className::_textures;\
    }\
    static opengl::Texture* _textures[textureCount];\
};\

#define DECLARATION_TEXTURES(className, textureCount)\
opengl::Texture* className::_textures[textureCount] = {nullptr};\

}

#endif